package com.dungeon.crawl;

import java.util.Random;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.View;

public class DungeonView extends View {

	//Vars holding various info about tiles
	int XtileCount, YtileCount, XscreenOffset, YscreenOffset;
	int tileSize = 16;
	Bitmap[] tileType = new Bitmap[20];
	//dummy paint var
	private final Paint paint = new Paint();
	//int values for all classes
	int knight = 0;
	int badGuy = 1;
	//Index int values for bitmaps
	int emptyTile = 0;
	int floorTile = 1;
	int wallTile = 2;
	int heroDown = 3;
	int heroLeft = 4;
	int heroRight = 5;
	int heroUp = 6;
	int heroDownW = 7;
	int heroLeftW = 8;
	int heroRightW = 9;
	int heroUpW = 10;
	int pVilDown = 11;
	int pVilLeft = 12;
	int pVilRight = 13;
	int pVilUp = 14;
	int pVilDownW = 15;
	int pVilLeftW = 16;
	int pVilRightW = 17;
	int pVilUpW = 18;
	//R.drawable ids for bitmaps of different classes
	int[] knightBitmap = {R.drawable.knight_up, R.drawable.knight_right, R.drawable.knight_down,
			R.drawable.knight_left, R.drawable.knight_up_walk, R.drawable.knight_right_walk,
			R.drawable.knight_down_walk, R.drawable.knight_left_walk};
	//2D array holding all tiles
	int[][] tileBitmaps = new int[0][0];
	//to check whether the screen has been measured yet
	boolean measured;
	Random randomgen = new Random();
	//The hero & monsters
	Creature player = new Creature();
	Creature[] monster = new Creature[10];
	//thread to be used later
	Thread walking;

	//View Constructor w/ variables
	public DungeonView(Context context) {
		super(context);
		setFocusable(true);
		setFocusableInTouchMode(true);

		//loads graphics for tile types
		loadTile(R.drawable.single_floor_tile, floorTile, context);
		loadTile(R.drawable.single_wall_tile, wallTile, context);
		loadTile(R.drawable.empty_tile, emptyTile, context);
		loadTile(knightBitmap[0], heroUp, context);
		loadTile(knightBitmap[1], heroRight, context);
		loadTile(knightBitmap[2], heroDown, context);
		loadTile(knightBitmap[3], heroLeft, context);
		loadTile(knightBitmap[4], heroUpW, context);
		loadTile(knightBitmap[5], heroRightW, context);
		loadTile(knightBitmap[6], heroDownW, context);
		loadTile(knightBitmap[7], heroLeftW, context);
		loadTile(R.drawable.p_badguy_down, pVilDown, context);
		loadTile(R.drawable.p_badguy_left, pVilLeft, context);
		loadTile(R.drawable.p_badguy_right, pVilRight, context);
		loadTile(R.drawable.p_badguy_up, pVilUp, context);
		loadTile(R.drawable.p_badguy_down_walk, pVilDownW, context);
		loadTile(R.drawable.p_badguy_left_walk, pVilLeftW, context);
		loadTile(R.drawable.p_badguy_right_walk, pVilRightW, context);
		loadTile(R.drawable.p_badguy_up_walk, pVilUpW, context);



		//thread for animating the hero's walking
		walking = new Thread(new Runnable() {
			public void run() {
				int move = 1;
				while(true) {
					try {
						synchronized (this) {
							wait(600);
						}
					}
					catch(Throwable t) {

					}
					switch(move) {
					case 0:
						move = 1;
						break;
					case 1:
						move = 0;
						break;
					}
					//Hero walks
					switch(tileBitmaps[player.getXCoord()][player.getYCoord()]) {
					case 3:
						tileBitmaps[player.getXCoord()][player.getYCoord()] = 7;
						break;
					case 4:
						tileBitmaps[player.getXCoord()][player.getYCoord()] = 8;
						break;
					case 5:
						tileBitmaps[player.getXCoord()][player.getYCoord()] = 9;
						break;
					case 6:
						tileBitmaps[player.getXCoord()][player.getYCoord()] = 10;
						break;
					case 7:
						tileBitmaps[player.getXCoord()][player.getYCoord()] = 3;
						break;
					case 8:
						tileBitmaps[player.getXCoord()][player.getYCoord()] = 4;
						break;
					case 9:
						tileBitmaps[player.getXCoord()][player.getYCoord()] = 5;
						break;
					case 10:
						tileBitmaps[player.getXCoord()][player.getYCoord()] = 6;
						break;
					}
					//Monsters walk
					for(int i = 0; i < 10; i++) {
						switch (tileBitmaps[monster[i].getXCoord()][monster[i].getYCoord()]) {
						case 11:
							tileBitmaps[monster[i].getXCoord()][monster[i].getYCoord()] = 15;
							break;
						case 12:
							tileBitmaps[monster[i].getXCoord()][monster[i].getYCoord()] = 16;
							break;
						case 13:
							tileBitmaps[monster[i].getXCoord()][monster[i].getYCoord()] = 17;
							break;
						case 14:
							tileBitmaps[monster[i].getXCoord()][monster[i].getYCoord()] = 18;
							break;
						case 15:
							tileBitmaps[monster[i].getXCoord()][monster[i].getYCoord()] = 11;
							break;
						case 16:
							tileBitmaps[monster[i].getXCoord()][monster[i].getYCoord()] = 12;
							break;
						case 17:
							tileBitmaps[monster[i].getXCoord()][monster[i].getYCoord()] = 13;
							break;
						case 18:
							tileBitmaps[monster[i].getXCoord()][monster[i].getYCoord()] = 14;
							break;
						}
					}
					//monster move
					if(move == 1) {
						for(int i = 0; i < 10; i++) {
							int direction = randomgen.nextInt(4) + 1;
							boolean temp = move(monster[i], direction);
							if(temp == true) {
								DungeonCrawlActivity.setCombat(temp);
								}
						}
					}
				}
			}
		});
	}

	/**
	 * Initializes the different bitmaps on canvases for different types of tiles needed.
	 * 
	 * @param tile
	 */
	public void loadTile(int drawable, int key, Context context) {
		//converts drawable to bitmap
		BitmapFactory.Options ops = new BitmapFactory.Options();
		ops.inJustDecodeBounds = true;
		//sets bitmap to a specific place in an array indicated by key
		Bitmap temp = BitmapFactory.decodeResource(context.getResources(), drawable);
		tileType[key] = Bitmap.createScaledBitmap(temp, tileSize, tileSize, false);
	}

	/**
	 * Sets the bitmap index of all tiles to 0 (empty).
	 */
	public void clearTiles() {
		for(int x = 0; x < XtileCount; x++) {
			for(int y = 0; y < YtileCount; y++) {
				tileBitmaps[x][y] = 1;
			}
		}
		for(int x = 0; x < XtileCount; x++) {
			tileBitmaps[x][0] = 2;
			tileBitmaps[x][YtileCount - 1] = 2;
		}
		for(int y = 0; y < YtileCount; y++) {
			tileBitmaps[0][y] = 2;
			tileBitmaps[XtileCount - 1][y] = 2;
		}
	}

	/**
	 * Establishes random starting position of Hero.
	 */
	public void initializeHeroPos() {
		int heroXCoord = randomgen.nextInt(XtileCount - 3) + 1;
		int heroYCoord = randomgen.nextInt(YtileCount - 3) + 1;
		tileBitmaps[heroXCoord][heroYCoord] = heroDown;
		player.setXCoord(heroXCoord);
		player.setYCoord(heroYCoord);
	}

	public void initializeMonsters() {
		for(int i = 0; i < 10; i++) {
			monster[i] = new Creature();
			int monsterXCoord = player.getXCoord();
			int monsterYCoord = player.getYCoord();
			while(monsterXCoord == player.getXCoord() && monsterYCoord == player.getYCoord()) {
				monsterXCoord = randomgen.nextInt(XtileCount - 3) + 1;
				monsterYCoord = randomgen.nextInt(YtileCount - 3) + 1;
				monster[i].setXCoord(monsterXCoord);
				monster[i].setYCoord(monsterYCoord);
			}
			tileBitmaps[monsterXCoord][monsterYCoord] = pVilDown;
		}
	}

	/**
	 * Generates the starting map, including random walls, items, & hero.
	 */
	public void setupMap() {
		clearTiles();
		initializeHeroPos();
		initializeMonsters();
		player.setProf(knight, heroLeft, heroRight, heroUp, heroDown); //<-- TEST
		for(int i = 0; i < 10; i++) {
			monster[i].setProf(badGuy, pVilLeft, pVilRight, pVilUp, pVilDown); //<-- TEST
		}
		walking.start();
	}

	/**
	 * Moves the hero or monster bitmap to an adjacent tile, checking for collision.
	 * 
	 * @param creature
	 * @param direction
	 */
	public boolean move(Creature creature, int direction) {
		switch(direction) {
		case 1:
			switch (tileBitmaps[creature.getXCoord()][creature.getYCoord() - 1]) {
			//if a floor tile
			case 1:
				tileBitmaps[creature.getXCoord()][creature.getYCoord()] = 1;
				tileBitmaps[creature.getXCoord()][creature.getYCoord() - 1] = creature.getBitmapIndex(direction);
				creature.setYCoord(creature.getYCoord() - 1);
				break;
				//start combat if hero or monsters run into each other
			case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10:
				return true;
			case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18:
				return true;
			}
			break;
		case 2:
			switch (tileBitmaps[creature.getXCoord() + 1][creature.getYCoord()]) {
			//if a floor tile
			case 1:
				tileBitmaps[creature.getXCoord()][creature.getYCoord()] = 1;
				tileBitmaps[creature.getXCoord() + 1][creature.getYCoord()] = creature.getBitmapIndex(direction);
				creature.setXCoord(creature.getXCoord() + 1);
				break;
				//start combat if hero or monsters run into each other
			case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10:
				return true;
			case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18:
				return true;
			}
			break;
		case 3:
			switch (tileBitmaps[creature.getXCoord()][creature.getYCoord() + 1]) {
			//if a floor tile
			case 1:
				tileBitmaps[creature.getXCoord()][creature.getYCoord()] = 1;
				tileBitmaps[creature.getXCoord()][creature.getYCoord() + 1] = creature.getBitmapIndex(direction);
				creature.setYCoord(creature.getYCoord() + 1);
				break;
				//start combat if hero or monsters run into each other
			case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10:
				return true;
			case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18:
				return true;
			}
			break;
		case 4:
			switch (tileBitmaps[creature.getXCoord() - 1][creature.getYCoord()]) {
			//if a floor tile
			case 1:
				tileBitmaps[creature.getXCoord()][creature.getYCoord()] = 1;
				tileBitmaps[creature.getXCoord() - 1][creature.getYCoord()] = creature.getBitmapIndex(direction);
				creature.setXCoord(creature.getXCoord() - 1);
				break;
				//start combat if hero or monsters run into each other
			case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10:
				return true;
			case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18:
				return true;
			}
			break;
		}
		synchronized (walking) {
			walking.notifyAll();
		}
		return false;
	}

	//Sets up tile info to prepare for drawing
	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		//Sets the # of tiles across & down based on view size
		XtileCount = (int) Math.floor(w / tileSize);
		YtileCount = (int) Math.floor(h / tileSize);
		//calculates space left over laterally & vertically, distributes to either side
		XscreenOffset = (w - (tileSize * XtileCount)) / 2;
		YscreenOffset = (h - (tileSize * YtileCount)) / 2;
		//resets size of grid
		tileBitmaps = new int[XtileCount][YtileCount];

		setupMap();
	}
	//drawing time!
	@Override
	public void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		for(int x = 0; x < XtileCount; x++) {
			for(int y = 0; y < YtileCount; y++) {
				if(tileBitmaps[x][y] > 0) {
					canvas.drawBitmap(tileType[tileBitmaps[x][y]], 1 + XscreenOffset + (x * tileSize),
							1 + YscreenOffset + (y * tileSize), paint);
				}
			}
		}
		invalidate();
	}
}
